//
// Created by tang on 2022/1/11.
//

#include "app_host_area.hpp"
#include "gui/dialog_names.h"
#include "imgui/imgui.h"
#include "imgui/IconsFontAwesome4.h"
#include "imgui/implot.h"
#include "event/events.hpp"
#include "gui/controls/custom_controls.hpp"
#include "imgui/imgui_internal.h"
#include "upgrade/upgrade_client.hpp"
#include "app/version.h"
#include "utils/app_utils.hpp"
#include "utils/os_utils.hpp"
#include "utils/log.hpp"
#include "imgui/imgui_stdlib.h"
#include "gui/form.hpp"

static ImVec2
GetCenterPopupWindowTLPos(const ImVec2& parentTopLeft, const ImVec2& parentSize, const ImVec2& popupSize) {
    return ImVec2((parentSize.x - popupSize.x) / 2 + parentTopLeft.x,
        (parentSize.y - popupSize.y) / 2 + parentTopLeft.y);
}

void AppHostArea::RenderComponent() {
    using namespace ImGui;

#if !NDEBUG
    static bool show_imgui_demo_win = false;
    static bool show_implot_demo_win = false;
#endif

    PushID(this);
    if (Begin("##TabWindow", nullptr,
        ImGuiWindowFlags_NoCollapse |
        ImGuiWindowFlags_NoMove |
        ImGuiWindowFlags_NoResize |
        ImGuiWindowFlags_NoBringToFrontOnFocus |
        ImGuiWindowFlags_MenuBar |
        ImGuiWindowFlags_NoTitleBar |
        ImGuiWindowFlags_NoDocking)) {
        if (static bool first_frame = true; first_frame) {

            // calculate all popup ids
            for (auto& x : m_dialogs_) {
                x.id = GetID(x.name.data());
            }
            m_msg_dlg_id_ = GetID("提示##MsgDlg");
            first_frame = false;
        }

        // App Menu
        if (BeginMenuBar()) {
            for (const auto& x : m_menus_) {
                if (x->Show(eMenu))
                    x->RenderContent(eMenu);
            }

            // fixed Menus
            if (BeginMenu(ICON_FA_QUESTION_CIRCLE_O " 帮助")) {
                static bool window_state_on_top = false;
                if (MenuItem(ICON_FA_ARROW_CIRCLE_UP " 窗口置顶", nullptr, &window_state_on_top))
                {
                    MainFromBase::ToggleWindowTopmost(window_state_on_top);
                }
#if !NDEBUG
                MenuItem(ICON_FA_ARROW_CIRCLE_RIGHT " ImGui Demo Window", nullptr, &show_imgui_demo_win);
                MenuItem(ICON_FA_ARROW_CIRCLE_RIGHT " ImPlot Demo Window", nullptr, &show_implot_demo_win);
                Separator();
#endif
                if (MenuItem(ICON_FA_ARROW_CIRCLE_UP " 检查软件更新"))
                    check_upgrade_async(false);
                Separator();
                if (MenuItem(ICON_FA_FILE_TEXT_O " 查看日志文件"))
                {
                    DefaultAppOpen(log_file_path());
                }
                Separator();
                if (MenuItem(ICON_FA_INFO_CIRCLE " 关于"))
                    App->ShowDialog(ABOUT_SOFTWARE_DIALOG_NAME);
                ImGui::EndMenu();
            }

            static const char* version_str = get_version_info_text();
            SameLine(0.f, GetContentRegionAvail().x - CalcTextSize(version_str).x);
            TextUnformatted(version_str);

            if (IsItemClicked()) {
                ImGui::SetClipboardText(version_str);
                SendNotification("已复制当前版本号");
            }

            EndMenuBar();
        }

        // App Widgets
        if (BeginTabBar("##AppHostArea", ImGuiTabBarFlags_None)) {
            for (auto& x : m_tabs_) {
                int flags = 0;
                if (!m_next_select_tab_.empty() && x.title == m_next_select_tab_) {
                    flags |= ImGuiTabItemFlags_SetSelected;
                    m_next_select_tab_.clear();
                }
                if (!x.view->Show(eTab))
                    continue;
                if (BeginTabItem(x.title.data(), nullptr, flags)) {
                    x.view->RenderContent(eTab);
                    EndTabItem();
                }
            }
            EndTabBar();
        }

        // Popups
        auto const viewportSize = GetMainViewport()->WorkSize;
        for (auto& x : m_dialogs_) {
            const auto PopupSize = x.view->DialogSize(viewportSize);
            ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar;
            SetNextWindowPos(GetCenterPopupWindowTLPos(GetMainViewport()->Pos, GetMainViewport()->Size, PopupSize),
                ImGuiCond_Always);
            SetNextWindowSize(PopupSize, ImGuiCond_Always);
            if (x.modal ? BeginPopupModal(x.name.data(), nullptr, flags | ImGuiWindowFlags_NoMove) : BeginPopup(
                x.name.data(), flags)) {
                x.view->RenderContent(eDialog);
                EndPopup();
            }
        }

        // 进度框
        if (m_progress_show_)
            OpenPopup("请稍后##ProgressDlg");
        const ImVec2 progress_dlg_size(GetFontSize() * 10, GetFontSize() * 6);
        SetNextWindowPos(GetCenterPopupWindowTLPos(GetMainViewport()->Pos, GetMainViewport()->Size, progress_dlg_size),
            ImGuiCond_Always);
        SetNextWindowSize(progress_dlg_size, ImGuiCond_Always);
        if (BeginPopupModal("请稍后##ProgressDlg")) {
            constexpr auto text = ICON_FA_BOLT " 任务进行中";
            SetCursorPosX((GetContentRegionAvail().x - CalcTextSize(text).x) / 2);
            TextUnformatted(text);
            SetCursorPosX((GetContentRegionAvail().x - 30) / 2);
            Spinner(15, 4, 10, ImColor(IM_COL32(0, 240, 16, 255)));

            if (!m_progress_show_)
                CloseCurrentPopup();
            EndPopup();
        }

        // 提示框
        static const auto DialogSize = ImVec2(GetFontSize ()*35, GetFontSize ()*20);
        SetNextWindowPos(GetCenterPopupWindowTLPos(GetMainViewport()->Pos, GetMainViewport()->Size, DialogSize),
            ImGuiCond_Always);
        SetNextWindowSize(DialogSize, ImGuiCond_Always);
        if (BeginPopupModal("提示##MsgDlg", nullptr,
            ImGuiWindowFlags_NoResize |
            ImGuiWindowFlags_NoMove
        )) {
            ImVec4 title_color(1.f, 1.f, 1.f, 1.f);
            const char* text = ICON_FA_BUG " 调试信息";
            switch (m_msg_type_) {
            case AppEvent::DialogMessage::eInfo:
                text = ICON_FA_INFO_CIRCLE " 消息";
                title_color = ImVec4(0.1f, 1.f, 0.1f, 1.f);
                break;
            case AppEvent::DialogMessage::eWarning:
                text = ICON_FA_EXCLAMATION_TRIANGLE " 警告";
                title_color = ImVec4(0.9f, 0.9f, 0.1f, 1.f);
                break;
            case AppEvent::DialogMessage::eError:
                text = ICON_FA_EXCLAMATION_CIRCLE " 错误";
                title_color = ImVec4(0.9f, 0.1f, 0.1f, 1.f);
                break;
            default:
                break;
            }

            float const max_x = (ImGui::GetContentRegionAvail() + ImGui::GetCursorScreenPos() - ImGui::GetWindowPos()).x;

            // center text
            SetCursorPosX((max_x - CalcTextSize(text).x) / 2.f);
            PushStyleColor(ImGuiCol_Text, title_color);
            TextUnformatted(text);
            PopStyleColor(1);
            //if (BeginChild("##MessageContent", ImVec2(0, -GetTextLineHeightWithSpacing() * 1.5f), ImGuiChildFlags_Border, ImGuiWindowFlags_NoScrollbar))
            //{
                //TextWrapped("%s", m_message_.c_str());
            //}
            //EndChild();
            InputTextMultiline("##MSG_CONTENT", &m_message_, ImVec2(-1, -GetTextLineHeightWithSpacing() * 1.5f), ImGuiInputTextFlags_ReadOnly);


            WindowBottomButtons(1, default_ok_cancel_button_text, [](int, void*) {
                CloseCurrentPopup();
                }, nullptr);

            EndPopup();
        }
    }
    End();
    PopID();

#if !NDEBUG
    if (show_imgui_demo_win)
        ImGui::ShowDemoWindow(&show_imgui_demo_win);

    if (show_implot_demo_win)
        ImPlot::ShowDemoWindow(&show_implot_demo_win);
#endif
}

void AppHostArea::ShowPopup(const std::string& id) {
    for (const auto& x : m_dialogs_) {
        if (id == x.name) {
            ImGui::OpenPopup(x.id);
        }
    }
}

AppHostArea::AppHostArea() : m_msg_dlg_id_(0), m_msg_type_(-1), m_listener_(App->Bus()), m_progress_show_(false) {
    m_listener_.listen<AppEvent::DialogMessage>([this](auto&& msg) {
        L_DEBUG("Opening Dialog, type = %d, msg = %s", (int)msg.type, msg.msg.c_str());
        if (msg.type != AppEvent::DialogMessage::eProgressDialog) {
            m_msg_type_ = msg.type;
            m_message_ = msg.msg;
            ImGui::OpenPopup(m_msg_dlg_id_);
        }
        else {
            m_progress_show_ = msg.show;
        }
    });

    m_listener_.listen<AppEvent::SelectTabEvent> ([this](auto &msg){
        if (msg.which < AppEvent::SelectTabEvent::eTabIdCount) {
            m_next_select_tab_ = TAB_NAME_OF(msg.which);
        }
    });
}

AppHostArea::~AppHostArea() {
    m_listener_.unlistenAll();
}

void AppHostArea::RegisterComponent(const ComponentPtr& view) {
    assert(view != nullptr);

    m_all_components_.emplace_back(view);

    const auto flag = view->Flags();

    if (flag & eMenu) {
        m_menus_.emplace_back(view);
    }
    if (flag & eTab) {
        const auto name = view->GetName(eTab);
        TabData d{ name, view };
        m_tabs_.emplace_back(d);
    }
    if (flag & eDialog) {
        const auto name = view->GetName(eDialog);
        const bool modal = name[0] == '!';
        DialogState state{ &name[static_cast<int>(modal)], 0, view, modal };
        m_dialogs_.emplace_back(state);
    }
}

void AppHostArea::OnInit()
{
    L_INFO("Host Init");
    for (auto &x: m_all_components_) {
        x->OnInit();
    }
}

void AppHostArea::OnCleanup()
{
    L_INFO("Host Cleanup");
    for (auto &x: m_all_components_) {
        x->OnCleanup();
    }
}
